iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Modern Web

你阿嬤成為網頁前端工程師的第一步系列 第 23

[Day 23] 阿嬤都看得懂的進階 CSS 選擇器與偽類選擇器

  • 分享至 

  • xImage
  •  

阿嬤都看得懂的進階 CSS 選擇器與偽類選擇器

前天我們在寫綠色貼紙的時候,各位阿嬤會不會覺得,我們也沒遵守到 DRY 原則呢?明明綠色貼紙和粉紅貼紙都是蓋版橫幅,只是顏色不同,我們卻整個都要重寫,也太麻煩了吧!

你可能會說:我沒這麼笨,我讓綠色貼紙沿用粉紅貼紙的樣式,然後用行內樣式的方式,另外把綠色貼紙改成綠色就好啦!那如果綠色貼紙中的文字需要是粉紅色,而粉紅色貼紙中的文字需要是綠色呢?把 color 也在行內樣式寫一次?這太麻煩了!

等等,我們是否可能把顏色的類別抽取出來,並且和橫幅蓋版的類別分開寫,然後讓粉紅貼紙和綠色貼紙都屬於兩個類呢?可以喔,我們只要把標籤中的 class 的 2 個類用半行空白隔開就可以了。所以寫起來會像這樣:

.banner{
  height: 20vh;
  width: 100vw;
}
.pink{
	background-color: pink;
	color: green;
}
.green{
	background-color: pink;
	color: green;
}
<div class="banner pink"><div>
.
.
.
<div class="banner green"><div>

看起來是很理想,不過如果我有很多其他粉紅和綠色的貼紙,也都共享 pink 和 green 這兩個類別,但是我只希望蓋版橫幅中的文字才是這樣的顏色配置,其他貼紙維持黑色,那我們又應該怎麼辦呢?有沒有可能我不要選擇所有 pink 類別中的標籤,而只選擇同時屬於 pink 和 banner 這 2 個類的標籤,才改變字體顏色呢?可以喔!我們需要的是更多種選擇器。

當我們想選擇那些同時具備某些類別的標籤時,我們必須在 .css 中,將這些類別全都寫在一起。注意,這些同時都需要具備的類別中間,不能有空格喔!也就是說,我們應該這樣寫:

.banner.pink{
	background-color: pink;
	color: green;
}
.banner.green{
	background-color: pink;
	color: green;
}

注意,.banner.pink 中間是沒有空格的!

另外,也要注意,這種組合幾個類別而做出選擇的進階選擇器,通常都需要放在原本類別的下方,因為 .css 檔案中,較下方出才寫的樣式,通常都會覆蓋掉較上方寫過的樣式。

那如果我們希望只有蓋版橫幅中的文字段落才置中放大,其它維持原樣,又應該怎麼寫呢?換句話說,我們只想選擇到那些屬於 .banner 類別的標籤中包含的文字段落。這時候,我們會在類別間放入空格,表示類別的從屬關係。舉例會比較好懂:

<div class="banner">
	<p>粉紅貼紙</p>
</div>
.banner p{
	text-align: center;
	line-height: 20vh;
	font-size: 5vmin;
	margin: 0;
}

這樣就可以將只有在屬於 .banner 類別的標籤中的 p 標籤加上這些樣式。(那個 margin 是為了清掉 p 標籤在某些瀏覽器預設的 1em 外距。) 在空格分隔類別的選擇器中,無論後面的類別在第幾層,都會被選擇到。換句話說,就算我的 HTML 標籤是

<div class="banner">
	<div>
	.
	.
	.
		<p>粉紅貼紙</p>
	.
	.
	.
	</div>
</div>

這個 p 標籤還是會被加上樣式。

由於在類別間加上空格以後,類別間會變成從屬關係,而非並列關係,所以是否加上空格就變得非常關鍵!這是新學習 CSS 選擇器的夥伴很容易混淆的地方,要仔細注意喔!

你可能會問,那如果我只想選擇 .banner 底下那層的 p 標籤,但不想選擇再更底層的 p 標籤,該怎麼辦呢?我們可以使用半形右角號 ">" 來表示這個關係。換句話說,如果上面的樣式改成這樣寫:

.banner>p{
	text-align: center;
	line-height: 20vh;
	font-size: 5vmin;
	margin: 0;
}

那麼

<div class="banner">
	<p>我會吃到樣式。</p>
	<div>
	.
	.
	.
		<p>我不會吃到樣式</p>
	.
	.
	.
	</div>
</div>

其中只有第一個 p 會吃到樣式喔!

但是,你會說,這樣我還是只能選擇到同層的所有同樣元素,沒辦法再選擇得更精確些嗎?例如,我就只想選擇那 8 張黃色貼紙中的第一張,該怎麼辦呢?我們總不會有個類,可以選擇出所有第一個元素吧!? 畢竟,「第一個元素」這種選擇法,是要看我們把哪些元素放在一起。

呃嗯,是也不是。我們確實有方法可以選到第一個元素,但也確實如同上述討論,我們必須先選擇出某群元素,才能選擇到這群元素中的第一個元素。這樣的選擇法,並不完全從類別出發,而是選擇到類別底下的,某個好像是類別的一堆(!?)元素。也因此,我們把這種選擇器,稱為「偽類選擇器」(psuedo-class selector)。換句話說,偽類選擇器會先選出

  1. 某個類別;然後再從中選擇出
  2. 某個子類。
    這個類別與子類中間,我們會用半形冒號 ":" 連接。例如,如果我們想選擇出黃色貼紙中的第一張貼紙,並且讓這個貼紙加上陰影 (box-shadow),我們就會這樣寫:
.yellow:first-child{
	box-shadow: 5px 5px 2px 1px gray;
}

其中 box-shadow 這個屬性的值分別是水平右移的長度、垂直下移的長度、陰影模糊的長度、陰影擴散的長度、以及陰影顏色。

那麼,我們可以選澤出所有編號為奇數的貼紙,並且加上藍色邊框嗎?沒問題。我們有第 n 個子元素 :nth-child() 這個偽類選擇器。這個選擇器的圓括弧裡可以填上某個數字,也可以填某個公式,就可以選擇到某個或某些子元素了。例如,:nth-child(1) 其實就是 :first-child;而我們想選澤出所有編號為奇數的貼紙,圓括弧中就可以填 2n+1:

.yellow:nth-child(2n+1){
	border: 1px solid blue;
}

當我們的元素個數不定,我們又想選擇最後一個子元素時, :last-child 這個偽類選擇器就派上用場了。讓我們把最後一張貼紙加上大圓角吧!

.yellow:last-child{
	border-radius: 5vmin;
}

今天介紹了許多進階的 CSS 選擇器,各位阿嬤可以自己 fork 底下這個 CodePen 回家練習喔!
https://codepen.io/LogosChen/pen/jOwzgpz


上一篇
[Day 22] 阿嬤都看得懂的元素容器與隱藏空格解法
下一篇
[Day 24] 阿嬤都看得懂的響應式網頁設計在幹嘛
系列文
你阿嬤成為網頁前端工程師的第一步30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言